﻿using System;
using CI;
using CI.Interfaces;
using CI.Mesopotamia.Dal;
using CI.Misc;
using NUnit.Framework;
using Rhino.Mocks;

namespace Mesopotamia.UnitTests.Organism
{
    [TestFixture]
    public class CellCollectionTests
    {
        // new mock repositry
        private IHostingEnvironment _hostingEnvironment;
        private CI.Organism.CellCollection _cells;
        private CI.Organism.Organism _organism;
        private readonly SimEnv _simEnv = SimEnv.Instance;

        /// <summary>Test Harness setup</summary>
        [SetUp]
        public void Setup()
        {
            _hostingEnvironment = new CI.Mesopotamia.MSRBHost(new MockHostingEnvironmentPhysical(), new CI.Mesopotamia.ScenarioLocalXML());
            _organism = new CI.Organism.Organism(_hostingEnvironment);
            _organism.Cells = new CI.Organism.CellCollection();
        }

        /// <summary>
        /// Check and retrieve neurons from the cells in the organism, whether they have been made through the dna or not yet
        /// </summary>
        [Test]
        public void NeuronsInCellsEqual()
        {
            // setup varibles
            _hostingEnvironment = new CI.Mesopotamia.MSRBHost(new MockHostingEnvironmentPhysical(), new CI.Mesopotamia.ScenarioLocalXML());
            _hostingEnvironment.HostingEnvironmentPhysical = MockRepository.GenerateStub<IHostingEnvironmentPhysical>();
            _hostingEnvironment.HostingEnvironmentPhysical.Stub(x => x.Registered(null)).Return(false).IgnoreArguments();
            var dal = new TestDAL();

            // create a organism
            dal.CreateiRobot(0, 0, _hostingEnvironment, true);

            // get the neurons
            var neurons = _hostingEnvironment.Organisms.Alive[0].Cells.Neurons();

            // check that 
            Assert.AreEqual(5, neurons.Count, "Expected 5 neurons");
        }

        /// <summary>argument checker</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void CellCollectionMutateNullOrganism()
        {
            _cells = new CI.Organism.CellCollection();
            _cells.Mutate(0, null);
        }

        /// <summary>mutate a cell colleciton and make sure we get one back</summary>
        [Test]
        public void CellCollectionMutateNotNull()
        {
            _cells = new CI.Organism.CellCollection();
            Assert.IsNotNull(_cells.Mutate(0, _organism), "cell collection not returned");
        }

        /// <summary>mutate a cell colleciton and make sure we get one back, with a cell</summary>
        [Test]
        public void CellCollectionMutateNotEmpty()
        {
            // create a new cell, this will automatically add it to the organism
            new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            // check that we get one back in the new collection
            Assert.Greater(_organism.Cells.Mutate(0, _organism).Count, 0, "cell collection not returned with any cells");
        }

        /// <summary>Search for a guid that does not exists</summary>
        [Test]
        public void CellCollectionFindNull()
        {
            // create a new cell, this will automatically add it to the organism
            new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            // search for it, should be able to  find it
            Assert.IsNull(_organism.Cells.Find(Guid.NewGuid()), "Cell should have not been found");
        }

        /// <summary>Search for a guid that does exists</summary>
        [Test]
        public void CellCollectionFindEqual()
        {
            // create a new cell, this will automatically add it to the organism
            ICell cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            // search for it, should be able to  find it
            Assert.AreEqual(cell, _organism.Cells.Find(cell.Guid), "Cell should have been found");
        }

        /// <summary>Search for a guid that does not exists via its guid as a string</summary>
        [Test]
        public void CellCollectionFindStringNull()
        {
            // create a new cell, this will automatically add it to the organism
            new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            // search for it, should be able to  find it
            Assert.IsNull(_organism.Cells.Find(Guid.NewGuid().ToString()), "Cell should have not been found");
        }

        /// <summary>Search for a guid that does exists via its guid as a string</summary>
        [Test]
        public void CellCollectionFindStringEqual()
        {
            // create a new cell, this will automatically add it to the organism
            ICell cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            // search for it, should be able to  find it
            Assert.AreEqual(cell, _organism.Cells.Find(cell.Guid.ToString()), "Cell should have been found");
        }

        /// <summary>This proceedure makes sure the cell collection checks the arguments</summary>
        [Test]
        public void EqualsValueTypesNullParameterFalse()
        {
            Assert.IsFalse(_organism.Cells.EqualsValueTypes(null), "result should be false, null cell collection comparison");
        }

        /// <summary>compares the values types of cells,actually the same cell</summary>
        [Test]
        public void EqualsValueTypesSameCellCollectionTrue()
        {
            // create a cell
            ICell cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            Assert.IsTrue(_organism.Cells.EqualsValueTypes(_organism.Cells), "result should be true, they are the same");
        }

        /// <summary>compares the values types of cells,should be false</summary>
        [Test]
        public void EqualsValueTypesSameCellCollectionFalse()
        {
            // create new cells
            ICell cell1 = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            ICell cell2 = new CI.Organism.iRobot(_organism, Guid.NewGuid());

            // just add one of them to the new collection
            ICellCollection cells = new CI.Organism.CellCollection {cell1};

            Assert.IsFalse(_organism.Cells.EqualsValueTypes(cells), "result should be false, they are diffent collecitons with different counts");
        }
    }
}